package cn.turboinfo.fuyang.api.domain.scheduler.usecase.profit

import cn.turboinfo.fuyang.api.domain.common.service.account.CompanyAccountService
import cn.turboinfo.fuyang.api.domain.common.service.custom.ServiceCustomService
import cn.turboinfo.fuyang.api.domain.common.service.profit.ProfitSharingRecordService
import cn.turboinfo.fuyang.api.domain.common.service.profit.ProfitSharingService
import cn.turboinfo.fuyang.api.domain.common.service.wechat.WechatPayService
import cn.turboinfo.fuyang.api.domain.common.usecase.AbstractUseCase
import cn.turboinfo.fuyang.api.domain.util.DateTimeFormatHelper
import cn.turboinfo.fuyang.api.entity.common.enumeration.account.AccountType
import cn.turboinfo.fuyang.api.entity.common.enumeration.common.EntityObjectType
import cn.turboinfo.fuyang.api.entity.common.enumeration.custom.ServiceCustomStatus
import cn.turboinfo.fuyang.api.entity.common.enumeration.order.ServiceOrderRefundStatus
import cn.turboinfo.fuyang.api.entity.common.enumeration.profit.ProfitSharingFailReason
import cn.turboinfo.fuyang.api.entity.common.enumeration.profit.ProfitSharingResult
import cn.turboinfo.fuyang.api.entity.common.enumeration.profit.ProfitSharingStatus
import cn.turboinfo.fuyang.api.entity.common.pojo.custom.QServiceCustom
import cn.turboinfo.fuyang.api.entity.common.pojo.custom.ServiceCustomUpdater
import cn.turboinfo.fuyang.api.entity.common.pojo.profit.ProfitSharingRecordCreator
import net.sunshow.toolkit.core.qbean.api.request.QPage
import net.sunshow.toolkit.core.qbean.api.request.QRequest
import net.sunshow.toolkit.core.qbean.helper.component.request.QPageRequestHelper
import org.springframework.stereotype.Component
import java.math.BigDecimal
import java.math.MathContext
import java.time.LocalDate
import java.time.LocalDateTime

@Component
class SchedulerServiceCustomProfitSharingPendingUseCase(
    private val wechatPayService: WechatPayService,
    private val serviceCustomService: ServiceCustomService,
    private val companyAccountService: CompanyAccountService,
    private val profitSharingService: ProfitSharingService,
    private val profitSharingRecordService: ProfitSharingRecordService,
) : AbstractUseCase<SchedulerServiceCustomProfitSharingPendingUseCase.InputData, SchedulerServiceCustomProfitSharingPendingUseCase.OutputData>() {

    override fun doAction(input: InputData): OutputData {

        val now = LocalDate.now()

        val request = QRequest.newInstance()
            .filterEqual(QServiceCustom.refundStatus, ServiceOrderRefundStatus.INIT)
            .filterEqual(QServiceCustom.customStatus, ServiceCustomStatus.COMPLETED)
            .filterEqual(QServiceCustom.profitSharingStatus, ProfitSharingStatus.PROCESSING)

        val requestPage = QPage.newInstance()
            .paging(0, 100)

        QPageRequestHelper.request(request, requestPage, serviceCustomService::findAll)
            .onEach {

                try {

                    var profitSharingStatus = ProfitSharingStatus.FINISHED

                    // 查询分账订单
                    val profitSharingList = profitSharingService.findByObjectId(it.id, EntityObjectType.SERVICE_CUSTOM)
                        .filter { profitSharing -> profitSharing.status.equals(ProfitSharingStatus.PROCESSING) }

                    for (profitSharing in profitSharingList) {

                        // 发起分账
                        val result = wechatPayService.findProfitsharing(
                            profitSharing.wxTransactionId,
                            profitSharing.id,
                        )

                        if ("FINISHED" == result.state) {
                            // 创建分账记录
                            if (result.receivers.isNotEmpty()) {
                                result.receivers.forEach { receiver ->

                                    // 处理分账结果
                                    val profitSharingResult: ProfitSharingResult = when (receiver.result) {
                                        ProfitSharingResult.SUCCESS.code -> ProfitSharingResult.SUCCESS

                                        ProfitSharingResult.CLOSED.code -> ProfitSharingResult.CLOSED

                                        else -> ProfitSharingResult.PENDING
                                    }

                                    // 处理失败原因
                                    val profitSharingFailReason: ProfitSharingFailReason = when (receiver.failReason) {
                                        ProfitSharingFailReason.ACCOUNT_ABNORMAL.code -> ProfitSharingFailReason.ACCOUNT_ABNORMAL
                                        ProfitSharingFailReason.NO_RELATION.code -> ProfitSharingFailReason.NO_RELATION
                                        ProfitSharingFailReason.RECEIVER_HIGH_RISK.code -> ProfitSharingFailReason.RECEIVER_HIGH_RISK
                                        ProfitSharingFailReason.RECEIVER_REAL_NAME_NOT_VERIFIED.code -> ProfitSharingFailReason.RECEIVER_REAL_NAME_NOT_VERIFIED
                                        ProfitSharingFailReason.NO_AUTH.code -> ProfitSharingFailReason.NO_AUTH
                                        ProfitSharingFailReason.RECEIVER_RECEIPT_LIMIT.code -> ProfitSharingFailReason.RECEIVER_RECEIPT_LIMIT
                                        ProfitSharingFailReason.PAYER_ACCOUNT_ABNORMAL.code -> ProfitSharingFailReason.PAYER_ACCOUNT_ABNORMAL

                                        else -> ProfitSharingFailReason.INIT
                                    }

                                    // 处理账户类型
                                    val accountType: AccountType = when (receiver.type) {
                                        AccountType.MERCHANT_ID.code -> AccountType.MERCHANT_ID
                                        AccountType.PERSONAL_OPENID.code -> AccountType.PERSONAL_OPENID

                                        else -> throw RuntimeException("账户类型不存在")
                                    }

                                    // 查询企业账户
                                    val companyAccount = companyAccountService.getByCompanyIdAndType(
                                        profitSharing.companyId,
                                        accountType
                                    )
                                        .stream()
                                        .findFirst()
                                        .orElseThrow { RuntimeException("企业账户不存在") }

                                    val builder = ProfitSharingRecordCreator
                                        .builder()
                                        .withProfitSharingId(profitSharing.id)
                                        .withWxDetailId(receiver.detailId)
                                        .withReceiverId(companyAccount.id)
                                        .withReceiverType(accountType)
                                        .withAmount(
                                            BigDecimal.valueOf(receiver.amount)
                                                .divide(BigDecimal(100), MathContext.UNLIMITED)
                                        )
                                        .withAccount(receiver.account)
                                        .withResult(profitSharingResult)
                                        .withFailReason(profitSharingFailReason)
                                        .withDescription(receiver.description)
                                        .withFinishTime(
                                            LocalDateTime.parse(
                                                receiver.finishTime,
                                                DateTimeFormatHelper.wechatDataTime
                                            )
                                        )

                                    profitSharingRecordService.save(builder.build())
                                }
                            }

                            // 修改 分账状态
                            profitSharingService.updateStatus(profitSharing.id, ProfitSharingStatus.FINISHED)

                        } else {
                            profitSharingStatus = ProfitSharingStatus.PROCESSING
                        }


                    }
                    if (ProfitSharingStatus.FINISHED == profitSharingStatus) {
                        // 修改订单状态
                        serviceCustomService.update(
                            ServiceCustomUpdater.builder(it.id)
                                .withProfitSharingStatus(profitSharingStatus)
                                .build()
                        )
                    }

                } catch (e: Exception) {
                    logger.error("分账失败, 订单编码： {} ", it.id, e)
                }

            }
        return OutputData()
    }

    class InputData : AbstractUseCase.InputData()

    class OutputData : AbstractUseCase.OutputData()

}
